<template>
  <teleport to="body">
    <transition name="dialog-fade">
      <div v-if="visible" class="common-dialog-wrapper" @click.self="handleClickModal">
        <div 
          class="common-dialog"
          :class="{ 'has-background': !!dialogBackground }"
          :style="{
            width: dialogWidth,
            backgroundImage: dialogBackground ? `url(${dialogBackground})` : 'none'
          }"
        >
          <!-- 标题栏 -->
          <div class="dialog-header">
            <h3 class="dialog-title">{{ title }}</h3>
            <div v-if="showClose" class="dialog-close" @click="handleClose">
              <el-icon :size="16"><CloseBold /></el-icon>
            </div>
          </div>
          
          <!-- 内容区域 -->
          <div class="dialog-body">
            <slot></slot>
          </div>
          
          <!-- 底部区域 -->
          <div v-if="$slots.footer" class="dialog-footer">
            <slot name="footer"></slot>
          </div>
        </div>
      </div>
    </transition>
  </teleport>
</template>

<script setup>
import { computed } from 'vue'
import { CloseBold } from '@element-plus/icons-vue'
import { pxVw } from '@/utils/pxtovw'

const props = defineProps({
  // 弹窗是否显示
  modelValue: {
    type: Boolean,
    default: false
  },
  // 弹窗宽度（支持数字或带单位的字符串）
  width: {
    type: [String, Number],
    default: 600
  },
  // 弹窗标题
  title: {
    type: String,
    default: ''
  },
  // 弹窗背景图
  background: {
    type: String,
    default: ''
  },
  // 是否显示关闭按钮
  showClose: {
    type: Boolean,
    default: true
  },
  // 是否点击遮罩关闭
  closeOnClickModal: {
    type: Boolean,
    default: false
  }
})

const emit = defineEmits(['update:modelValue'])

const visible = computed({
  get: () => props.modelValue,
  set: (val) => emit('update:modelValue', val)
})

const dialogWidth = computed(() => {
  // 如果是数字，转换为 vw
  if (typeof props.width === 'number') {
    return pxVw(props.width)
  }
  // 如果是字符串且只包含数字，转换为 vw
  if (typeof props.width === 'string' && /^\d+$/.test(props.width)) {
    return pxVw(Number(props.width))
  }
  // 如果是带 px 的字符串，提取数字并转换
  if (typeof props.width === 'string' && props.width.endsWith('px')) {
    const num = parseInt(props.width)
    return pxVw(num)
  }
  // 其他情况直接返回（如已经是 vw 或其他单位）
  return props.width
})

const dialogBackground = computed(() => {
  return props.background
})

const handleClose = () => {
  visible.value = false
}

const handleClickModal = () => {
  if (props.closeOnClickModal) {
    handleClose()
  }
}
</script>

<style lang="scss" scoped>
@import '@/style/utils.scss';

.dialog-fade-enter-active,
.dialog-fade-leave-active {
  transition: opacity 0.3s;
  .common-dialog {
    transition: transform 0.3s;
  }
}

.dialog-fade-enter-from,
.dialog-fade-leave-to {
  opacity: 0;
  .common-dialog {
    transform: scale(0.9);
  }
}

.common-dialog-wrapper {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 9999;
  
  .common-dialog {
    background-size: 100% 100%;
    background-repeat: no-repeat;
    border-radius: px2vw(4);
    max-height: 80vh;
    display: flex;
    flex-direction: column;
    
    // 无背景图时的默认样式
    &:not(.has-background) {
      background-color: rgba(2, 24, 34, 0.95);
      border: px2vw(2) solid rgba(0, 255, 244, 0.3);
      box-shadow: 0 px2vw(8) px2vw(24) rgba(0, 0, 0, 0.5);
    }
    
    // 有背景图时隐藏边框和标题栏下边框、footer上边框
    &.has-background {
      .dialog-header {
        border-bottom: none;
      }
      
      .dialog-footer {
        border-top: none;
      }
    }
    
    .dialog-header {
      height: px2vw(38);
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 0 px2vw(16);
      border-bottom: px2vw(1) solid rgba(0, 255, 244, 0.2);
      
      .dialog-title {
        font-size: px2vw(18);
        font-weight: 900;
        letter-spacing: px2vw(2);
        line-height: px2vw(18);
        background: linear-gradient(180deg, rgba(238, 238, 238, 1) 0%, rgba(238, 238, 238, 1) 40%, rgba(59, 135, 202, 1) 100%);
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        background-clip: text;
        filter: drop-shadow(0px px2vw(2) px2vw(3) rgba(0, 0, 0, 0.5));
      }
      
      .dialog-close {
        width: px2vw(24);
        height: px2vw(24);
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;
        transition: opacity 0.3s;
        
        &:hover {
          opacity: 0.8;
        }
        
        :deep(.el-icon) {
          color: rgba(175, 215, 230, 1);
        }
      }
    }
    
    .dialog-body {
      flex: 1;
      padding: px2vw(24);
      overflow-y: auto;
      
      &::-webkit-scrollbar {
        width: px2vw(6);
      }
      
      &::-webkit-scrollbar-track {
        background: rgba(0, 0, 0, 0.1);
        border-radius: px2vw(3);
      }
      
      &::-webkit-scrollbar-thumb {
        background: rgba(0, 255, 244, 0.3);
        border-radius: px2vw(3);
        
        &:hover {
          background: rgba(0, 255, 244, 0.5);
        }
      }
    }
    
    .dialog-footer {
      padding: px2vw(16) px2vw(24) px2vw(24);
      border-top: px2vw(1) solid rgba(0, 255, 244, 0.2);
      display: flex;
      justify-content: flex-end;
      align-items: center;
      gap: px2vw(12);
    }
  }
}
</style>